/******************************************************************************
 * @file     OTA.c
 * @brief    OTA线程
 * @author   Ruilist
 * @date     2025-08-18
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *
 * @par 日志:
 * - V1.0.0 2025-08-18 Ruilist
 *****************************************************************************/

//******************************** Includes *********************************//

#include "OTA.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

uint8_t g_Ymodem_rec_bufA[1030];
uint8_t g_Ymodem_rec_bufB[1030];

static uint8_t g_ota_cmd[4];

//******************************** Defines **********************************//

//*********************Thread_Func **********************//

osThreadId_t         OTA_taskHandle;
const osThreadAttr_t OTA_task_attributes = {
    .name       = "OTA_task",
    .stack_size = 512 * 4,
    .priority   = (osPriority_t)osPriorityNormal1,
};

osThreadId_t         download_taskHandle;
const osThreadAttr_t Download_task_attributes = {
    .name       = "Download_task",
    .stack_size = 512 * 4,
    .priority   = (osPriority_t)osPriorityNormal1,
};

void download_task( void *argument );

//*********************Thread_Func **********************//

//*********************Queue_Handler ********************//

QueueHandle_t     Queue_OTA_cmd     = NULL;
QueueHandle_t     Queue_data_buffer = NULL;
SemaphoreHandle_t xMutex            = NULL;

//*********************Queue_Handler ********************//

//******************************** Declaring ********************************//

void ota_cmd_array_init( void )
{
    g_ota_cmd[0] = 0;
    g_ota_cmd[1] = 0;
    g_ota_cmd[2] = 0;
    g_ota_cmd[3] = 0;
}

void SoftReset( void )
{
    log_i( "SoftReset\r\n" );
    __set_FAULTMASK( 1 );
    NVIC_SystemReset();
}

static int8_t Key_Scan()
{
    for ( uint16_t cnt = 0; cnt < 400; cnt++ )
    {
        if ( GPIO_PIN_RESET == HAL_GPIO_ReadPin( KEY_GPIO_Port, KEY_Pin ) )
        {
            osDelay( 20 );
            if ( GPIO_PIN_RESET == HAL_GPIO_ReadPin( KEY_GPIO_Port, KEY_Pin ) )
            {

                return 1;
            }
        }
        osDelay( 50 );
    }

    return -1;
}

void ota_task( void *argument )
{
    int32_t            app_data_length = 0;
    static ota_state_t ota_state       = wait_req_download;
    uint8_t            cmd_length      = 0;
    uint8_t            ack_cmd[]       = { 0x44, 0x55, 0x66 };

    uint8_t ee_ota_state = 0x00;
    // 清除eeprom的OTA状态
    ee_WriteBytes( &ee_ota_state, 0x00, 1 );

    log_i( "Start ota_task!\r\n" );

    for ( ;; )
    {
        switch ( ota_state )
        {
        case wait_req_download:
            // 等待下载指令
            HAL_UARTEx_ReceiveToIdle_DMA( &huart1, g_ota_cmd, 4 );
            // 接收并判断队列指令
            xQueueReceive( Queue_OTA_cmd, &cmd_length, portMAX_DELAY );
            if ( 3 == cmd_length )
            {
                if ( ( 0x11 == g_ota_cmd[0] ) && ( 0x22 == g_ota_cmd[1] ) && ( 0x33 == g_ota_cmd[2] ) )
                {
                    // 切换下载状态
                    ota_state = ota_download;
                    // 创建下载线程
                    download_taskHandle = osThreadNew( download_task, NULL, &Download_task_attributes );
                    Queue_data_buffer   = xQueueCreate( 1, sizeof( uint8_t * ) );
                    xMutex              = xSemaphoreCreateMutex();

                    ee_ota_state = 0x11;
                    ee_WriteBytes( &ee_ota_state, 0x00, 1 );
                }
                else
                {
                    ota_cmd_array_init();
                }
            }
            else
            {
                ota_cmd_array_init();
            }

            break;
        case ota_download:
            // 进入下载状态
            log_i( "ota_download!\r\n" );
            app_data_length = Ymodem_Receive( g_Ymodem_rec_bufA, g_Ymodem_rec_bufB );
            if ( 0 < app_data_length )
            {
                ota_state = wait_req_update;
                // 发送下载完成指令
                HAL_UART_Transmit( &huart1, ack_cmd, 3, 1000 );
                // 删除下载线程及相关资源
                xSemaphoreTake( xMutex, portMAX_DELAY );
                xSemaphoreGive( xMutex );

                W25Q64_WriteData_End();

                vTaskDelete( download_taskHandle );
                vQueueDelete( Queue_data_buffer );
                vSemaphoreDelete( xMutex );

                ee_ota_state = 0x22;
                ee_WriteBytes( &ee_ota_state, 0x00, 1 );

                osDelay( 10 );
                uint8_t read = 0;
                ee_ReadBytes( &read, 0x00, 1 );
                log_i( "read 0x00 is[%d]\r\n", read );

                // 写入数据长度
                ee_WriteBytes( (uint8_t *)&app_data_length, 0x01, sizeof( app_data_length ) );
            }
            else
            {
                ota_state = wait_req_download;
                // 删除下载线程及相关资源
                vTaskDelete( download_taskHandle );
                vQueueDelete( Queue_data_buffer );
                vSemaphoreDelete( xMutex );
            }

            break;
        case wait_req_update:
            // 等待更新指令
            HAL_UARTEx_ReceiveToIdle_DMA( &huart1, g_ota_cmd, 4 );
            xQueueReceive( Queue_OTA_cmd, &cmd_length, portMAX_DELAY );
            if ( 3 == cmd_length )
            {
                if ( ( 0x77 == g_ota_cmd[0] ) && ( 0x88 == g_ota_cmd[1] ) && ( 0x99 == g_ota_cmd[2] ) )
                {
                    ota_state = ota_end;
                }
                else
                {
                    ota_cmd_array_init();
                }
            }
            else
            {
                ota_cmd_array_init();
            }
            break;
        case ota_end:
            log_i( "ota_end!\r\n" );
            if ( 1 == Key_Scan() )
            {
                SoftReset();
            }
            else
            {
                ota_state = wait_req_download;
            }
            break;
        default:
            break;
        }
    }
}

void download_task( void *argument )
{
    uint8_t *p_data = NULL;
    int32_t *p_size = NULL;
    // 第一帧数据一定是数据的长度
    xQueueReceive( Queue_data_buffer, &p_size, portMAX_DELAY );
    // 需要擦除掉flash size对应的所有扇区
    // TODO:
    xSemaphoreGive( xMutex );
    while ( 1 )
    {
        if ( pdTRUE == xQueuePeek( Queue_data_buffer, &p_data, portMAX_DELAY ) )
        {
            xSemaphoreTake( xMutex, portMAX_DELAY );
            xQueueReceive( Queue_data_buffer, &p_data, portMAX_DELAY );

            if ( p_data == NULL )
            {
                continue;
            }
            // 写入W25q64
            W25Q64_WriteData( p_data, g_packet_length );
            log_i( "W25Q64_WriteData ok\r\n" );
            xSemaphoreGive( xMutex );
        }
    }
}

//******************************** Declaring ********************************//
